package cn.shafish.nettycommon.dispatcher;

import cn.shafish.nettycommon.codec.Invocation;
import cn.shafish.nettycommon.util.JacksonUtils;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Sharable注解标记这个ChannelHandler可以被多个ChannelHandlerContext使用，也是为了线程安全考虑
 * 为什么不继承SimpleChannelInboundHandler<Invocation>，SimpleChannelInboundHandler抽象类也是一个入站处理器，
 *      但在其channelRead方法中会进行一个ReferenceCountUtil.release(msg)操作，会释放掉接收的msg
 */
@ChannelHandler.Sharable
public class MessageDispatcher extends SimpleChannelInboundHandler<Invocation> {

    @Autowired
    private MessageHandlerContainer messageHandlerContainer;

    private final ExecutorService executor =  Executors.newFixedThreadPool(200);


    /*    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        super.channelRead(ctx, msg);
    }*/

    /**
     * 在SimpleChannelInboundHandler中使用了模板方法，
     * 固定的处理逻辑在SimpleChannelInboundHandler.channelRead方法执行
     * 在channelRead中再调用channelRead0处理信息
     * @param ctx
     * @param invocation
     * @throws Exception
     */
    protected void channelRead0(ChannelHandlerContext ctx, Invocation invocation) throws Exception {
        // 获得 type 对应的 MessageHandler 处理器
        MessageHandler messageHandler = messageHandlerContainer.getMessageHandler(invocation.getType());
        // 获得  MessageHandler 处理器 的消息类
        Class<? extends Message> messageClass = MessageHandlerContainer.getMessageClass(messageHandler);
        // 解析消息
        Message message = JacksonUtils.fromJson(invocation.getMessage(), messageClass);
        // 执行逻辑
        executor.submit(new Runnable() {
            @Override
            public void run() {
                // noinspection unchecked
                messageHandler.execute(ctx.channel(), message);
            }
        });
    }
}
